package com.css.fxfzdzzh.modules.basicData.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.PageUtil;
import com.css.fxfzdzzh.base.annotation.EntityValue;
import com.css.fxfzdzzh.base.exception.ShpFieldException;
import com.css.fxfzdzzh.base.response.RestResponse;
import com.css.fxfzdzzh.constants.GeomTypeEnum;
import com.css.fxfzdzzh.constants.RedisKeyConstants;
import com.css.fxfzdzzh.constants.YNEnum;
import com.css.fxfzdzzh.modules.basicData.entity.LandForm;
import com.css.fxfzdzzh.modules.basicData.entity.SensingImage;
import com.css.fxfzdzzh.modules.basicData.landslideSite.entity.FieldDesc;
import com.css.fxfzdzzh.modules.basicData.landslideSite.vo.TableVo;
import com.css.fxfzdzzh.modules.basicData.repository.impl.LandformRepository;
import com.css.fxfzdzzh.modules.basicData.vo.ListVo;
import com.css.fxfzdzzh.modules.basicData.vo.QueryByVersionParam;
import com.css.fxfzdzzh.util.PlatformDateUtils;
import com.css.fxfzdzzh.util.UUIDGenerator;
import com.css.fxfzdzzh.util.fileParsing.ParsingResult;
import com.css.fxfzdzzh.util.fileParsing.shp.ShpAnalyticUtil;
import com.css.fxfzdzzh.web.PlatformSessionContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Dbj
 * @date 2023年02月25日  14:55
 */
@Slf4j
@Service
public class LandformService {

    @Resource
    LandformRepository landformRepository;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    public RestResponse getYwData(QueryByVersionParam queryByVersionParam) {
        List<LandForm> list = landformRepository.getYwData(queryByVersionParam);
        if (queryByVersionParam.getPage() != null && queryByVersionParam.getRows() != null) {
            Long total = landformRepository.countByDataVersion(queryByVersionParam);
            return RestResponse.succeed(new HashMap<String, Object>() {{
                put("data", list);
                put("title", getFieldTable());
                put("total", total);
                put("page", queryByVersionParam.getPage());
                put("rows", queryByVersionParam.getRows());
                put("totalPage", PageUtil.totalPage(total, queryByVersionParam.getRows()));
            }});
        } else {
            return RestResponse.succeed(new HashMap<String, Object>() {{
                put("data", list);
                put("title", getFieldTable());
            }});
        }
    }

    public List<TableVo> getFieldTable(){
        Field[] declaredFields = LandForm.class.getDeclaredFields();
        List<TableVo> list = new ArrayList<>();
        if(declaredFields.length>0){
            for(Field field : declaredFields){
                FieldDesc fieldDesc = new FieldDesc();
                field.setAccessible(true);
                EntityValue entityValue = field.getAnnotation(EntityValue.class);
                if(entityValue==null){
                    continue;
                }
                TableVo vo = new TableVo();
                vo.setLabel(entityValue.name());
                vo.setProp(field.getName());
                list.add(vo);
            }
        }
        return list;
    }
    public List<FieldDesc>  getFieldDesc() {
        Field[] declaredFields = LandForm.class.getDeclaredFields();
        List<FieldDesc> list = new ArrayList<>();
        AtomicInteger sno = new AtomicInteger(1);
        if(declaredFields.length>0){
            for(Field field : declaredFields){
                FieldDesc fieldDesc = new FieldDesc();
                field.setAccessible(true);
                EntityValue entityValue = field.getAnnotation(EntityValue.class);
                if(entityValue==null){
                    continue;
                }
                String type = entityValue.type();
                String must = entityValue.must();
                String name = entityValue.name();
                String desc = entityValue.desc();
                fieldDesc.setType(type).setMust(must).setName(name).setDesc(desc).setSno(sno.get());
                sno.getAndAdd(1);
                list.add(fieldDesc);
            }
        }
        return list;
    }
    public List<LandForm> getYwData(String versionCode, String geom) {
        return landformRepository.getYwData(versionCode, geom);
    }


    public void updateByVersion(String tempVersionCode, String versionCode, Integer dataRangeCountry) {
        landformRepository.updateByVersion(tempVersionCode,versionCode,dataRangeCountry);
    }

    public void deleteByVersion(String versionCode) {
        landformRepository.deleteByVersion(versionCode);
    }

    public void updateLs(String versionCode, String tempVersionCode) {
        landformRepository.updateLs(versionCode,tempVersionCode);
    }

    public RestResponse saveShpTemporaryData(ParsingResult shpData) {
        //生成临时版本号
        //生成临时版本号
        try {
            String dataVersion = UUID.randomUUID().toString().replaceAll("-", "");
            List<LandForm> list = getList(shpData.getShpList(), dataVersion);
            if (list.size()>0){
                landformRepository.byShpBatchSave(list);
            }

            ListVo listVo = new ListVo("0", null, dataVersion, "地貌", null, list);
            return RestResponse.succeed(listVo);
        } catch (ShpFieldException e) {
            log.error(e.getMessage() + "\n错误数据 > {}", shpData.getShpList());
            return RestResponse.fail(e.getMessage());
        } catch (IndexOutOfBoundsException e1) {
            return RestResponse.fail("字段数量不符合要求");
        }
    }

    private List<LandForm> getList(List<List<Object>> shpList, String dataVersion) throws ShpFieldException{
        String userID = PlatformSessionContext.getUserID(); // 获取当前登录用户
        ArrayList<LandForm> arrayList = new ArrayList<>();
        for (int i = 0; i < shpList.size(); i++) {
            List<Object> list = shpList.get(i);
            LandForm obj = new LandForm();
            //临时版本号
            obj.setDataVersion(dataVersion);
            //当前用户
            obj.setCreateUser(userID);
            obj.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
            obj.setDelFlag(YNEnum.N.toString());
            if("".equals(list.get(0))|| list.get(0)==null){
                throw new ShpFieldException("序号"+list.get(1)+"的空间数据有误");
            }else{
                obj.setGeom(ShpAnalyticUtil.checkGeomTypeOf(list.get(0).toString(), GeomTypeEnum.MULTIPOLYGON));
            }
            if("".equals(list.get(1))|| list.get(1)==null){
                throw new ShpFieldException("序号"+list.get(1)+"的地貌名称不能为空");
            }else{
                String dslName = ShpAnalyticUtil.getStringVal(list.get(2).toString(), "地貌名称", true);
                Integer values=null;
                switch (dslName){
                    //黄土塬/黄土阶地/黄土坡地/黄土丘陵/黄土梁/黄土峁/其他
                    case "黄土塬":values=1;break;
                    case "黄土阶地":values=2;break;
                    case "黄土坡地":values=3;break;
                    case "黄土丘陵":values=4;break;
                    case "黄土梁":values=5;break;
                    case "黄土峁":values=6;break;
                    case "其他":values=7;break;
                    default:throw new ShpFieldException("序号"+list.get(1)+"的地貌名称不合规范！(黄土塬/黄土阶地/黄土坡地/黄土丘陵/黄土梁/黄土峁/其他)");
                }
                obj.setDslName(dslName);
                obj.setValues1(values);
            }

            if("".equals(list.get(1))|| list.get(1)==null){
                throw new ShpFieldException("序号不能为空");
            }else{
                obj.setDslNumber(ShpAnalyticUtil.getStringVal(list.get(1).toString(), "序号", true));
            }
            obj.setDslId(UUIDGenerator.getUUID());
            arrayList.add(obj);
        }
        return arrayList;
    }
    public String getVersionCodeNum() {
        return this.getVersionCode();
    }
    public synchronized String getVersionCode() {
        String dataVersionCodeSerialNumber = stringRedisTemplate.opsForValue().get(RedisKeyConstants.DATA_LANDFORM_NUMBER_KEY);
        if (StringUtils.isBlank(dataVersionCodeSerialNumber)) {
            dataVersionCodeSerialNumber = "001";
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            String t = String.valueOf(Integer.parseInt(dataVersionCodeSerialNumber) + 1);
            for (int i = t.length(); i < 5; i++) {
                stringBuilder.append("0");
            }
            dataVersionCodeSerialNumber = stringBuilder.append(t).toString();
        }
        stringRedisTemplate.opsForValue().set(RedisKeyConstants.DATA_LANDFORM_NUMBER_KEY, dataVersionCodeSerialNumber);
        stringRedisTemplate.expireAt(RedisKeyConstants.DATA_LANDFORM_NUMBER_KEY, Date.from(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).toInstant(ZoneOffset.of("+8"))));
        return DateUtil.format(new Date(), "yyyyMMdd") + "CQ" + dataVersionCodeSerialNumber;
    }

    public Integer getValidDataNum(String versionCode) {
        return landformRepository.getValidDataNum(versionCode);
    }

    public LandForm getYwDetails(String id) {
        return landformRepository.getYwDetails(id);
    }
}
